<template>
  <div :class="`tab-header`">
    <div id="editor">
      <Input
        :class="`button-common`"
        type="file"
        ref="fielinput"
        accept=".pdf"
        id="fielinput"
        @change="uploadFile"
      />
      <Button :class="`button-common`" v-if="isSign" @click="handleSign">点击预览</Button>
      <Button :class="`button-common`" v-else @click="handleSign">点击签名</Button>
      <Button :class="`button-common`" @click="handleUndo">撤回</Button>
      <Button :class="`button-common`" @click="handleClear">清除</Button>
      <Button :class="`button-common`" @click="savePDF">下载PDF</Button>
    </div>
    <div>
      <div id="parentDiv">
        <div ref="contentDiv" id="contentDiv"></div>
      </div>
    </div>
  </div>
</template>
<script lang="ts">
  import { Button, Input } from 'ant-design-vue';
  import { defineComponent, ref } from 'vue';
  import SmoothSignature from 'smooth-signature';
  import * as pdfJS from 'pdfjs-dist';
  import * as pdfjsWorker from 'pdfjs-dist/build/pdf.worker.entry';
  import JsPDF from 'jspdf';

  pdfJS.GlobalWorkerOptions.workerSrc = pdfjsWorker;

  export default defineComponent({
    components: { Button, Input },
    setup() {
      const fielinput = ref(null);
      const contentDiv = ref(null);

      //签名相关
      const isSign = ref(false); //控制是否允许签名
      const canvass = ref([]); //保存所有画布元素
      const signatures = ref([]); //所有签名对象
      const historys = ref([]); //签名历史 用于回退或者清除，因为是一次性展示多个页面，会存在多个包装好的签名对象，存放历史列表方便操作

      //PDF展示相关
      const pdfData = ref(null); // PDF 内容
      const scale = ref(2); //放大比例 ，有的时候展示可能会比较模糊，可以放大展示

      //上传控件选择事件，加载选中的 PDF 文件
      const uploadFile = (e: Event) => {
        // 断言为HTMLInputElement
        const target = e.target as HTMLInputElement;
        const files = target.files;
        let reader = new FileReader();
        reader.readAsDataURL(files[0]);
        reader.onload = () => {
          let data = atob(reader.result.substring(reader.result.indexOf(',') + 1));
          loadPdfData(data);
        };
      };
      //加载PDF
      function loadPdfData(data) {
        //移除所有旧的 Canvas 画布元素
        removeChild();
        //重置对象状态
        isSign.value = false;
        canvass.value = [];
        signatures.value = [];
        // 引入pdf.js的字体，如果没有引用的话字体可能会不显示
        let CMAP_URL = 'https://unpkg.com/pdfjs-dist@2.0.943/cmaps/';
        //读取base64的pdf流文件
        pdfData.value = pdfJS.getDocument({
          data: data, // PDF base64编码
          cMapUrl: CMAP_URL,
          cMapPacked: true,
        });
        //渲染全部页面
        renderAllPages();
      }
      //移除页面上旧的元素
      function removeChild() {
        var content = contentDiv.value;
        var child = content.lastElementChild;
        while (child) {
          content.removeChild(child);
          child = content.lastElementChild;
        }
      }
      //渲染全部页面
      function renderAllPages() {
        pdfData.value.promise.then((pdf) => {
          for (let i = 1; i <= pdf.numPages; i++) {
            pdf.getPage(i).then((page) => {
              let viewport = page.getViewport(scale.value);
              //动态生成 Canvas 画布并设置宽高
              var canvas = document.createElement('canvas');
              canvas.height = viewport.height;
              canvas.width = viewport.width;

              let ctx = canvas.getContext('2d');
              let renderContext = {
                canvasContext: ctx,
                viewport: viewport,
              };
              //将 PDF 页面渲染到 Canvas 上
              page.render(renderContext).then(() => {});
              //将画布包装成 SmoothSignature
              initSignatureCanvas(canvas);
              //将画布元素放入到 div 容器中展示
              canvass.value.push(canvas);
              contentDiv.value.appendChild(canvas);
            });
          }
        });
      }
      //初始化签名对象
      const initSignatureCanvas = (canvas) => {
        const optionSign = {
          width: canvas.width,
          height: canvas.height,
          maxHistoryLength: 100, //最大历史记录
        };

        const signature = new SmoothSignature(canvas, optionSign);
        //初始化时 先移除它内部添加的监听事件，默认不能签名
        signature.removeListener();
        //签名对象 addHistory 方法做一下修改，在原来逻辑的基础上添加这一行
        // historys.value.push(signature); 方便处理历史签名记录
        signature.addHistory = function () {
          if (!signature.maxHistoryLength || !signature.canAddHistory) return;
          signature.canAddHistory = false;
          signature.historyList.push(signature.canvas.toDataURL());
          signature.historyList = signature.historyList.slice(-signature.maxHistoryLength);
          historys.value.push(signature);
        };
        signatures.value.push(signature);
      };
      /**
       * 签名预览转换
       * 允许签名：调用 signature 对象中的 addListener 方法，添加监听事件
       * 不允许签名：调用 signature 对象中的 removeListener 方法，移除监听事件
       */
      const handleSign = () => {
        isSign.value = !isSign.value;
        if (signatures.value && signatures.value.length > 0) {
          if (isSign.value) {
            for (let i = 0; i < signatures.value.length; i++) {
              signatures.value[i].addListener();
            }
          } else {
            for (let i = 0; i < signatures.value.length; i++) {
              signatures.value[i].removeListener();
            }
          }
        }
      };
      /**
       * 后退操作
       * 调用历史签名记录中的 signature 对象中的 undo 方法会撤回当前对象中的最后一次的画线记录
       * 注意：后退后不要忘记将列表中最后一个元素移除
       */
      const handleUndo = () => {
        if (historys.value && historys.value.length > 0) {
          const signatureList = historys.value;
          let signature = signatureList.pop();
          signature.undo();
          historys.value = signatureList;
        }
      };
      // 清除所有 循环把所有签名历史都处理了
      const handleClear = async () => {
        while (historys.value && historys.value.length > 0) {
          handleUndo();
        }
      };
      // 下载PDF
      const savePDF = () => {
        //生成新的 PDF
        let pdf = new JsPDF('', 'pt', 'a4');
        if (canvass.value.length > 0) {
          //将 canvas 内容转化成 JPEG
          for (let i = 0; i < canvass.value.length; i++) {
            const ccccc = canvass.value[i];
            let pageData = ccccc.toDataURL('image/JPEG');
            if (i > 0) {
              pdf.addPage();
            }
            pdf.addImage(
              pageData,
              'JPEG',
              0,
              0,
              ccccc.width / scale.value,
              ccccc.height / scale.value,
            );
          }
          //到处新的PDF 
          return pdf.save('TestPdf.pdf');
        }
      };

      return {
        fielinput,
        uploadFile,
        contentDiv,
        isSign,
        handleSign,
        handleUndo,
        handleClear,
        savePDF,
      };
    },
    mounted() {},
  });
</script>
<style lang="less" scoped>
  .tab-header {
    background: rgb(146, 175, 138);
    padding-left: 1%;
    padding-right: 1%;
  }
  .button-common {
    margin-right: 2px;
    max-width: 200px;
  }
  #contentDiv {
    // display: inline-block;
  }
  #parentDiv {
    position: absolute;
    overflow: auto;
    top: 5%;
    bottom: 1%;
    display: inline-block;
  }
  #signShower {
    position: absolute;
    left: 50%;
    top: 5%;
    bottom: 1%;
    display: inline-block;
  }
</style>
